package io.gitee.caoxiaoyu97.log4j.defender.log4j2;

import io.gitee.caoxiaoyu97.log4j.defender.provider.LogDefenderProvider;

import java.util.LinkedList;
import java.util.List;

import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.layout.PatternLayout;
import org.apache.logging.log4j.core.pattern.ConverterKeys;
import org.apache.logging.log4j.core.pattern.LogEventPatternConverter;
import org.apache.logging.log4j.core.pattern.PatternFormatter;
import org.apache.logging.log4j.core.pattern.PatternParser;
import org.apache.logging.log4j.util.PerformanceSensitive;

@Plugin(name = "defender", category = "Converter")
@ConverterKeys({"defender"})
@PerformanceSensitive({"allocation"})
public class Log4j2DefenderConverter
        extends LogEventPatternConverter {
    private final List<PatternFormatter> formatters;

    private Log4j2DefenderConverter(List<PatternFormatter> formatters) {
        super("defender", "defender");
        this.formatters = formatters;
    }

    public static Log4j2DefenderConverter newInstance(Configuration config, String[] options) {
        if (options.length < 1) {
            LOGGER.error("Incorrect number of options on {}: expected 1 received {}: {}", "defender",
                    Integer.valueOf(options.length), options);
            return null;
        }
        PatternParser parser = PatternLayout.createPatternParser(config);
        List<PatternFormatter> formatters = new LinkedList<>();
        for (String option : options) {
            formatters.addAll(parser.parse(option));
        }
        return new Log4j2DefenderConverter(formatters);
    }

    public void format(LogEvent event, StringBuilder toAppendToOrigin) {
        StringBuilder toAppendTo = toAppendToOrigin;
        if (null != this.formatters) {
            for (int i = 0; i < this.formatters.size(); i++) {
                PatternFormatter formatter = this.formatters.get(i);
                formatter.format(event, toAppendTo);
            }
        }

        if (!LogDefenderProvider.getInstance().isEnabled()) {
            return;
        }

        String loggerName = event.getLoggerName();
        if (!LogDefenderProvider.getInstance().isInLoggerScope(loggerName)) {
            return;
        }

        toAppendTo = LogDefenderProvider.getInstance().doReplace(toAppendTo);
    }
}
